﻿using System;
using System.Collections.Generic;
using System.Text;
using System.Net;
using System.IO;
using System.Xml;

namespace ArrowWebParts
{
    public class ReportDefinition
    {
        public String title;
        public String description;
        public String template;
        public String[] dataSourceNameArray;
        
        //Use the dataSourcePathArray for framework files
        public String[] dataSourcePathArray;

        //Templates that run directly without a framework file, will set an object array of DataDefinitions
        public DataDefinition[] dataSourceObjectArray;

        public String[] variableHiddenArray;
        public String[] variableNameArray;
        public String[] variableRequiredArray;
        public String[] variableTypeArray;
        public String[] variableDescriptionArray;
        public String[] variableDefaultArray;
        public String[] variableSelectCountArray;
        public String[] variableSelectAllArray;
        public String[] variableSelectValueArray;

        //We need to optionally store a save location for the report. 
        //So the required guid objects are for an SPSite, SPWeb, and SPDocumentLibrary. 
        //Optional is an SPFolder object.
        public string reportName;
        public Guid saveSPSite;
        public Guid saveSPWeb;
        public Guid saveSPDocumentLib;
        public Guid saveSPFolder;

        /// <summary>
        /// [VARIABLEDATANAME] values. [VARIABLEDATANAME] values are datasource names in the template,
        /// so for instance, the default data source will be null or empty string; and if you have a
        /// data source named "My_Data", that will be the value of [VARIABLEDATANAME] for any variables
        /// associated with it.
        /// </summary>
        public String[] variableDataNameArray;


        public ReportDefinition(string _title, string _description, string _template, string[] _dataSourceNameArray,
                                DataDefinition[] _dataSourceObjectArray, string[] _variableNameArray, string[] _variableRequiredArray,
                                string[] _variableTypeArray, string[] _variableDescriptionArray, string[] _variableDefaultArray,
                                string[] _variableSelectCountArray, string[] _variableSelectAllArray, string[] _variableSelectValueArray,
                                string[] _variableDataNameArray)
        {
            title = _title;
            description = _description;
            template = _template;
            dataSourceNameArray = _dataSourceNameArray;
            dataSourceObjectArray = _dataSourceObjectArray;
            variableNameArray = _variableNameArray;
            variableRequiredArray = _variableRequiredArray;
            variableTypeArray = _variableTypeArray;
            variableDescriptionArray = _variableDescriptionArray;
            variableDefaultArray = _variableDefaultArray;
            variableSelectCountArray = _variableSelectCountArray;
            variableSelectAllArray = _variableSelectAllArray;
            variableSelectValueArray = _variableSelectValueArray;
            variableDataNameArray = _variableDataNameArray;
            variableHiddenArray = new String[variableDataNameArray.Length];
            
            //saveSPDocumentLib = new Guid();
            //saveSPFolder = new Guid();
            //saveSPSite = new Guid();
            //saveSPWeb = new Guid();
        }
        /// <summary>
        /// creates report Definition info by parsing the file at the given file path
        /// </summary>
        /// <param name="fullUrl">full url of the report Definition file</param>
        public ReportDefinition(String fullUrl)
        {
            // get the file stream of the Definition
            MemoryStream rptDefStream = ArrowUtils.GetSPFileStream(fullUrl);

            ctor(rptDefStream);
        }

        /// <summary>
        /// Creates a new ReportDefinition by parsing the specified MemoryStream
        /// </summary>
        /// <param name="rptDefStream"></param>
        public ReportDefinition(MemoryStream rptDefStream)
        {
            ctor(rptDefStream);
        }

        /// <summary>
        /// Creates a new ReportDefinition by parsing the specified MemoryStream
        /// </summary>
        /// <param name="rptDefStream"></param>
        private void ctor(MemoryStream rptDefStream)
        {
            XmlDocument xmlDoc = new XmlDocument();
            xmlDoc.Load(rptDefStream);

            title = xmlDoc.SelectSingleNode("/reportdef/title").InnerText;
            description = xmlDoc.SelectSingleNode("/reportdef/description").InnerText;
            if (description == null)
                description = string.Empty;
            template = xmlDoc.SelectSingleNode("/reportdef/template").InnerText;
            collectDataSourceInfo(xmlDoc);
            collectVariableInfo(xmlDoc);
            collectRunDefaults(xmlDoc);
        }

        private void collectRunDefaults(XmlDocument xmlDoc)
        {
            XmlNode runDefaultsNode = xmlDoc.SelectSingleNode("/reportdef/runDefaults");
            if (runDefaultsNode != null)
            {
                saveSPSite = new Guid(runDefaultsNode.SelectSingleNode("saveSite").InnerText);
                saveSPWeb = new Guid(runDefaultsNode.SelectSingleNode("saveWeb").InnerText);
                saveSPDocumentLib = new Guid(runDefaultsNode.SelectSingleNode("saveLib").InnerText);
                saveSPFolder = new Guid(runDefaultsNode.SelectSingleNode("saveFolder").InnerText);
                reportName = runDefaultsNode.SelectSingleNode("reportName").InnerText;
            }
        }

        private void collectVariableInfo(XmlDocument xmlDoc)
        {
            XmlNodeList varNodes = xmlDoc.SelectNodes("/reportdef/variable");
            variableHiddenArray = new string[varNodes.Count];
            variableNameArray = new string[varNodes.Count];
            variableRequiredArray = new string[varNodes.Count];
            variableTypeArray = new string[varNodes.Count];
            variableDescriptionArray = new string[varNodes.Count];
            variableDefaultArray = new string[varNodes.Count];
            variableSelectCountArray = new string[varNodes.Count];
            variableSelectAllArray = new string[varNodes.Count];
            variableSelectValueArray = new string[varNodes.Count];
            variableDataNameArray = new string[varNodes.Count];
            
            int i = 0;
            foreach (XmlNode varNode in varNodes)
            {
                variableNameArray[i] = varNode.SelectSingleNode("variableName").InnerText;
                variableDescriptionArray[i] = varNode.SelectSingleNode("variableDescription").InnerText;
                variableRequiredArray[i] = varNode.SelectSingleNode("variableRequired").InnerText;
                variableHiddenArray[i] = varNode.SelectSingleNode("variableHidden").InnerText;
                variableTypeArray[i] = varNode.SelectSingleNode("variableType").InnerText;
                variableDefaultArray[i] = varNode.SelectSingleNode("variableDefault").InnerText;
                variableDataNameArray[i] = varNode.SelectSingleNode("variableDataName").InnerText;
                variableSelectCountArray[i] = varNode.SelectSingleNode("variableSelectCount").InnerText;
                variableSelectAllArray[i] = varNode.SelectSingleNode("variableSelectAll").InnerText;
                variableSelectValueArray[i] = varNode.SelectSingleNode("variableSelectValue").InnerText;
                i++;
            }
        }

        private void collectDataSourceInfo(XmlDocument xmlDoc)
        {
            XmlNodeList dsNodes = xmlDoc.SelectNodes("/reportdef/dataSource");
            dataSourceNameArray = new string[dsNodes.Count];
            dataSourcePathArray = new string[dsNodes.Count];

            int i = 0;
            foreach (XmlNode dsNode in dsNodes)
            {
                // get the data source name & path
                dataSourceNameArray[i] = dsNode.SelectSingleNode("dataSourceName").InnerText;
                dataSourcePathArray[i] = dsNode.SelectSingleNode("dataSourcePath").InnerText;
                i++;
            }
        }

        public DataDefinition[] getDataSources()
        {
            if (dataSourceObjectArray != null && dataSourceObjectArray.Length > 0)
            {
                return dataSourceObjectArray;
            }
            DataDefinition[] dataSources = new DataDefinition[dataSourceNameArray.Length];
            for (int dsInd = 0; dsInd < dataSourceNameArray.Length; dsInd++)
            {
                dataSources[dsInd] = new DataDefinition(dataSourcePathArray[dsInd]);
            }
            return dataSources;
        }
    }
}
